home
***
CD-ROM
|
disk
|
FTP
|
other
***
search
/
Celestin Apprentice 5
/
Apprentice-Release5.iso
/
Source Code
/
Libraries
/
WASTE 1.2
/
WASTE Tabs
/
WETabHooks.c
next >
Wrap
Text File
|
1996-05-19
|
7KB
|
252 lines
/*
* WETabHooks.c
*
* Hooks for adding tab support to WASTE.
*
* Original code by Mark Alldritt
* Line breaking code by Dan Crevier
* Support for horizontal scrolling by Bert Seltzer
* Maintenance by John C. Daub
* Further modifications by Marco Piovanelli
*
*/
#include "WETabHooks.h"
#ifndef kTabWidth
#define kTabWidth 32
#endif
/*
If kTabWidth is a power of two, we can exploit the fact that
(x % kTabWidth) == (x & (kTabWidth - 1))
and replace those expensive modulus (%) operators with much
cheaper ANDs. (From a suggestion by Mark Valence.)
*/
#define IS_POWER_OF_TWO(x) (((x) & ((x) - 1)) == 0)
#if IS_POWER_OF_TWO(kTabWidth)
/* inline short MOD(short x) { return (x & (kTabWidth - 1)); } */
#define MOD(x) (((short) (x)) & (kTabWidth - 1))
#else
/* inline short MOD(short x) { return (x % kTabWidth); } */
#define MOD(x) (((short) (x)) % kTabWidth)
#endif
/* inline short FIXROUND(Fixed f) { return ((f + 0x00008000) >> 16); } */
#define FIXROUND(f) ((short) (((f) + 0x00008000) >> 16))
#ifndef BSL
#define BSL( A, B ) (((long) (A)) << (B))
#endif
static const Point kOneToOneScaling = { 1, 1 } ;
pascal void _WETabDrawText(Ptr pText, long textLength, Fixed slop,
JustStyleCode styleRunPosition, WEReference we)
{
#pragma unused(slop, styleRunPosition)
LongRect destRect;
long beginChar = 0;
long ii;
short tabWidth;
short destLeft;
Point penPos;
WEGetDestRect(&destRect, we);
destLeft = (short) destRect.left;
for ( ii = 0; ii < textLength; ii++ )
{
if (pText[ii] == '\t')
{
DrawText(pText, beginChar, ii - beginChar);
/* advance the pen to the next tab stop */
GetPen(&penPos);
tabWidth = kTabWidth - MOD(penPos.h - destLeft);
MoveTo(penPos.h + tabWidth, penPos.v);
beginChar = ii + 1;
}
} /* for */
DrawText(pText, beginChar, textLength - beginChar);
}
pascal long _WETabPixelToChar(Ptr pText, long textLength, Fixed slop,
Fixed *width, char *edge, JustStyleCode styleRunPosition,
Fixed hPos, WEReference we)
{
#pragma unused(we)
long beginChar = 0;
long offset = 0;
long ii;
Fixed lastWidth;
Fixed tabWidth;
/* loop through every character in the segment looking for tabs */
for ( ii = 0; ii < textLength; ii++ )
{
/* exit now if width has gone negative */
/* (i.e., if we have found which glyph was hit) */
if (*width <= 0)
break;
/* tab found? */
if (pText[ii] == '\t')
{
/* calculate the width of the sub-segment preceding the tab */
lastWidth = *width;
offset += PixelToChar(pText + beginChar, ii - beginChar, slop,
lastWidth, (unsigned char *) edge, width, styleRunPosition,
kOneToOneScaling, kOneToOneScaling);
beginChar = ii + 1;
/* hit point past sub-segment? */
if (*width >= 0)
{
/* increment hPos by width of sub-segment preceding the tab */
hPos += (lastWidth - *width);
/* calculate the width of the tab "glyph" (as a Fixed value) */
tabWidth = BSL(kTabWidth - MOD(FIXROUND(hPos)), 16);
/* increment hPos by width of tab character */
hPos += tabWidth;
/* hit point within tab glyph? */
if (*width < tabWidth)
{
/* yes: determine which half of tab glyph was hit */
if (*width > (tabWidth >> 1))
{
*edge = kTrailingEdge; /* second (trailing) edge of tab */
offset++;
}
else
*edge = kLeadingEdge; /* first (leading) edge of tab */
/* returning -1 (as Fixed) in width means we're finished */
*width = 0xFFFF0000;
}
else {
/* hit point is past tab: keep looping */
offset++;
*width -= tabWidth;
}
} /* if (*width >= 0) */
} /* if tab found */
} /* for */
/* no more tabs in this segment: process the last sub-segment */
if (*width >= 0)
{
lastWidth = *width;
offset += PixelToChar(pText + beginChar, textLength - beginChar, slop,
lastWidth, (unsigned char *) edge, width, styleRunPosition,
kOneToOneScaling, kOneToOneScaling);
}
/* round width to nearest integer value */
/* this is supposed to fix an incompatibility with the WorldScript Power Adapter */
*width = (*width + 0x00008000) & 0xFFFF0000;
return offset;
}
pascal short _WETabCharToPixel(Ptr pText, long textLength, Fixed slop,
long offset, short direction, JustStyleCode styleRunPosition,
long hPos, WEReference we)
{
#pragma unused(slop, direction, styleRunPosition)
LongRect destRect;
long beginChar = 0;
long ii;
short width;
short destLeft;
short totalWidth = 0;
WEGetDestRect(&destRect, we);
destLeft = (short) destRect.left;
/* measure text up to offset, if offset is within this segment */
if (offset < textLength)
textLength = offset;
for ( ii = 0; ii < textLength; ii++ )
{
if (pText[ii] == '\t')
{
/* calculate the pixel width of the subsegment preceding the tab */
width = TextWidth(pText, beginChar, ii - beginChar);
totalWidth += width;
hPos += width;
/* calculate tab width */
width = kTabWidth - MOD(hPos - destLeft);
totalWidth += width;
hPos += width;
/* go to next subsegment */
beginChar = ii + 1;
}
} /* for */
/* calculate width of remaining characters */
width = TextWidth(pText, beginChar, textLength - beginChar);
totalWidth += width;
return totalWidth;
}
pascal StyledLineBreakCode _WETabLineBreak(Ptr pText, long textLength,
long textStart, long textEnd, Fixed *textWidth,
long *textOffset, WEReference we)
{
LongRect destRect;
long beginChar = textStart;
long ii;
Fixed tabWidth;
short destWidth;
StyledLineBreakCode breakCode = smBreakOverflow;
WEGetDestRect(&destRect, we);
destWidth = (short) (destRect.right - destRect.left);
for ( ii = textStart; ii < textEnd; ii++ )
{
if (pText[ii] == '\t')
{
/* do previous "segment" */
breakCode = StyledLineBreak(pText, textLength, beginChar,
ii, 0, textWidth, textOffset);
if ((breakCode != smBreakOverflow) || (ii >= textLength))
break;
beginChar = ii + 1;
/* calculate tab width (as a Fixed value) */
tabWidth = BSL(kTabWidth - MOD(destWidth - FIXROUND(*textWidth)), 16);
/* if tabWidth > pixelWidth we break in tab */
/* don't move tab to next line */
if (tabWidth > *textWidth)
{
breakCode = smBreakWord;
*textOffset = ii + 1;
break;
}
else
*textWidth -= tabWidth;
}
} /* for */
/* do last sub-segment */
if ((ii - beginChar >= 0) && (breakCode == smBreakOverflow))
breakCode = StyledLineBreak(pText, textLength, beginChar, ii, 0, textWidth, textOffset);
return breakCode;
}